package sf.database.jdbc.sql;

import sf.spring.util.CollectionUtils;
import sf.tools.ArrayUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;

/**
 * 通用common
 */
public class CommonSql {

    public static void fillStatement(PreparedStatement pst, Object paras) throws SQLException {
        if (paras.getClass().isArray()) {
            fillArrayStatement(pst, (Object[]) paras);
        } else if (Collection.class.isAssignableFrom(paras.getClass())) {
            Type[] types = ((ParameterizedType) paras.getClass().getGenericSuperclass()).getActualTypeArguments();
            Type type = null;
            if (types != null && types.length > 0) {
                type = types[0];
            }
            if (SQLParameter.class.equals(type)) {
                fillSQLStatement(pst, (List<SQLParameter>) paras);
            } else {
                fillListStatement(pst, (List<Object>) paras);
            }
        } else {
            fillArrayStatement(pst, paras);
        }
    }


    /**
     * 设置值
     * @param pst
     * @param paras
     * @throws SQLException
     */
    public static void fillListStatement(PreparedStatement pst, List<Object> paras) throws SQLException {
        int i = 1;
        if (CollectionUtils.isEmpty(paras)) {
            return;
        }
        for (Object val : paras) {
            if (val != null) {
                val = fixBugs(val);
            }
            //setNull无需处理,jdbc会自己处理
            //pst.setNull(i++, Types.VARCHAR);
            pst.setObject(i++, val);
        }
    }

    /**
     * 设置值
     * @param pst
     * @param paras
     * @throws SQLException
     */
    public static void fillArrayStatement(PreparedStatement pst, Object... paras) throws SQLException {
        if (ArrayUtils.isEmpty(paras)) {
            return;
        }
        for (int i = 0; i < paras.length; i++) {
            Object val = paras[i];
            if (val != null) {
                val = fixBugs(val);
            }
            //setNull无需处理,jdbc会自己处理
            //pst.setNull(i + 1, Types.VARCHAR);
            pst.setObject(i + 1, val);
        }
    }

    /**
     * 设置值
     * @param pst
     * @param paras
     * @throws SQLException
     */
    public static void fillSQLStatement(PreparedStatement pst, List<SQLParameter> paras) throws SQLException {
        if (CollectionUtils.isEmpty(paras)) {
            return;
        }
        int i = 1;
        for (SQLParameter p : paras) {
            if (p.getColumnMapping() != null) {
                p.getColumnMapping().getHandler().set(pst, p.getValue(), i);
            } else if (p.getHandler() != null) {
                p.getHandler().set(pst, p.getValue(), i);
            } else {
                int jdbcType = p.getJdbcType();
                //setNull无需处理,jdbc会自己处理
                //pst.setNull(i, jdbcType);
                Object val = p.getValue();
                if (val != null) {
                    val = fixBugs(val);
                }
                if (jdbcType != 0) {
                    pst.setObject(i, val, jdbcType);
                } else {
                    pst.setObject(i, val);
                }
            }
            i++;
        }
    }

    /**
     * 1.修复oracle,postgresql只认Timestamp;<br>
     * 2.枚举的处理.
     * @param val
     * @return
     */
    private static Object fixBugs(Object val) {
        if (val.getClass() == java.util.Date.class) {
            val = new Timestamp(((java.util.Date) val).getTime());
        } else if (val.getClass().isEnum()) {
            val = val.toString();
        }
        return val;
    }
}
